home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / WINPROGS / WINSRC20.ZIP / CALCMAND.ASM < prev    next >
Assembly Source File  |  1990-09-10  |  25KB  |  841 lines

  1. ;    CALCMAND.ASM - Mandelbrot/Julia Set calculation Routines
  2.  
  3. ;    This module runs as part of an overlay with calcfrac.c.
  4. ;    It must not be called from anywhere other than calcfrac.
  5.  
  6. ;    The routines in this code perform Mandelbrot and Julia set
  7. ;    calculations using 32-bit integer math as opposed to the
  8. ;    "traditional" floating-point approach.
  9.  
  10. ;    This code relies on several tricks to run as quickly as it does.
  11.  
  12. ;    One can fake floating point arithmetic by using integer
  13. ;    arithmetic and keeping track of the implied decimal point
  14. ;    if things are reasonable -- and in this case, they are.
  15. ;    I replaced code that looked like: z = x*y with code that
  16. ;    looks like:
  17. ;            ix = x * ifudge         (outside the loops)
  18. ;            iy = y * ifudge
  19. ;            ....
  20. ;            iz = (ix * iy) / ifudge     (inside the loops)
  21. ;    (and keep remembering that all the integers are "ifudged" bigger)
  22.  
  23. ;    The 386 has native 32-bit integer arithmetic, and (briefly) keeps
  24. ;    64-bit values around after 32-bit multiplies.    If the result is
  25. ;    divided down right away, you've got 64-bit arithmetic.   You just
  26. ;    have to ensure that the result after the divide is <= 32 bits long.
  27. ;    CPUs predating the 386 have to emulate 32-bit arithmetic using
  28. ;    16-bit arithmetic, which is significantly slower.
  29.  
  30. ;    Dividing is slow -- but shifting is fast, and we can select our
  31. ;    "fudge factor" to be a power of two, permitting us to use that
  32. ;    method instead.   In addition, the 386 can perform 32-bit wide
  33. ;    shifting -- and even 64-bit shifts with the following logic:
  34. ;            shdr    eax,edx,cl
  35. ;            shr    edx,cl
  36. ;    so we make sure that our "fudge factor" is a power of 2 and shift
  37. ;    it down that way.
  38. ;    Calcmand is hardcoded for a fudge factor of 2**29.
  39.  
  40.  
  41. ;                    Bert Tyler
  42.  
  43.  
  44. ;             required for compatibility if Turbo ASM
  45. IFDEF ??version
  46. MASM51
  47. QUIRKS
  48. ENDIF
  49.  
  50. .MODEL    medium,c
  51. DGROUP          group   _DATA,_DATA2
  52.  
  53. .8086
  54.  
  55.     ; these must NOT be in any segment!!
  56.     ; this get's rid of TURBO-C fixup errors
  57.  
  58.     extrn    keypressed:far        ; this routine is in 'general.asm'
  59.     extrn    getakey:far        ; this routine is in 'general.asm'
  60.     extrn    iplot_orbit:far     ; this routine is in 'calcfrac.c'
  61.     extrn    scrub_orbit:far     ; this routine is in 'calcfrac.c'
  62.  
  63. _DATA2        segment DWORD PUBLIC 'DATA'
  64.  
  65. FUDGEFACTOR    equ    29        ; default (non-potential) fudgefactor
  66.  
  67. ; ************************ External variables *****************************
  68.  
  69.     extrn    fractype:word        ; == 0 if Mandelbrot set, else Julia
  70.     extrn    inside:word        ; "inside" color, normally 1 (blue)
  71.     extrn    creal:dword, cimag:dword ; Julia Set Constant
  72.     extrn    delmin:dword        ; min increment - precision required
  73.     extrn    maxit:word        ; maximum iterations
  74.     extrn    lm:dword        ; magnitude bailout limit
  75.  
  76.     extrn    row:word, col:word    ; current pixel to calc
  77.     extrn    color:word        ; color calculated for the pixel
  78.  
  79.     extrn    reset_periodicity:word    ; nonzero if to be reset
  80.     extrn    kbdcount:word        ; keyboard counter
  81.  
  82.     extrn    cpu:word        ; cpu type: 86, 186, 286, or 386
  83.  
  84.     extrn    show_orbit:word     ; "show-orbit" flag
  85.     extrn    orbit_ptr:word        ; "orbit pointer" flag
  86.     extrn    periodicitycheck:word    ; no periodicity if zero
  87.  
  88.     public    linitx,linity        ; caller sets these
  89.     public    savedmask        ; caller sets this
  90.  
  91. ; ************************ Internal variables *****************************
  92.  
  93.         align    4
  94. x        dd    0        ; temp value: x
  95. y        dd    0        ; temp value: y
  96. absx        dd    0        ; temp value: abs(x)
  97. linitx        dd    0        ; initial value, set by calcfrac
  98. linity        dd    0        ; initial value, set by calcfrac
  99. savedmask    dd    0        ; saved values mask
  100. savedx        dd    0        ; saved values of X and Y iterations
  101. savedy        dd    0        ;  (for periodicity checks)
  102. k        dw    0        ; iteration countdown counter
  103. oldcolor    dw    0        ; prior pixel's escape time k value
  104. savedand    dw    0        ; AND value for periodicity checks
  105. savedincr    dw    0        ; flag for incrementing AND value
  106. period        db    0        ; periodicity, if in the lake
  107.  
  108. _DATA2        ends
  109.  
  110. .CODE
  111.  
  112. ; ***************** Function calcmandasm() **********************************
  113.  
  114.     public    calcmandasm
  115.  
  116. calcmandasm proc    uses di si
  117.  
  118.     sub    ax,ax            ; clear ax
  119.     cmp    periodicitycheck,ax    ; periodicity checking disabled?
  120.     je    initoldcolor        ;  yup, set oldcolor 0 to disable it
  121.     cmp    reset_periodicity,ax    ; periodicity reset?
  122.     je    short initparms     ; inherit oldcolor from prior invocation
  123.     mov    ax,maxit        ; yup.    reset oldcolor to maxit-250
  124.     sub    ax,250            ; (avoids slowness at high maxits)
  125. initoldcolor:
  126.     mov    oldcolor,ax        ; reset oldcolor
  127.  
  128. initparms:
  129.     mov    ax,word ptr creal    ; initialize x == creal
  130.     mov    dx,word ptr creal+2    ;  ...
  131.     mov    word ptr x,ax        ;  ...
  132.     mov    word ptr x+2,dx     ;  ...
  133.  
  134.     mov    ax,word ptr cimag    ; initialize y == cimag
  135.     mov    dx,word ptr cimag+2    ;  ...
  136.     mov    word ptr y,ax        ;  ...
  137.     mov    word ptr y+2,dx     ;  ...
  138.  
  139.     mov    ax,maxit        ; setup k = maxit
  140.     inc    ax            ; (+ 1)
  141.     mov    k,ax            ;  (decrementing to 0 is faster)
  142.  
  143.     cmp    fractype,1        ; julia or mandelbrot set?
  144.     je    short dojulia        ; julia set - go there
  145.  
  146. ;    (Tim wants this code changed so that, for the Mandelbrot,
  147. ;    Z(1) = (x + iy) + (a + ib).  Affects only "fudged" Mandelbrots.
  148. ;    (for the "normal" case, a = b = 0, and this works, too)
  149. ;    cmp    word ptr x,0        ; Mandelbrot shortcut:
  150. ;    jne    short doeither        ;  if creal = cimag = 0,
  151. ;    cmp    word ptr x+2,0        ; the first iteration can be emulated.
  152. ;    jne    short doeither        ;  ...
  153. ;    cmp    word ptr y,0        ;  ...
  154. ;    jne    short doeither        ;  ...
  155. ;    cmp    word ptr y+2,0        ;  ...
  156. ;    jne    short doeither        ;  ...
  157. ;    dec    k            ; we know the first iteration passed
  158. ;    mov    dx,word ptr linitx+2    ; copy x = linitx
  159. ;    mov    ax,word ptr linitx    ;  ...
  160. ;    mov    word ptr x+2,dx     ;  ...
  161. ;    mov    word ptr x,ax        ;  ...
  162. ;    mov    dx,word ptr linity+2    ; copy y = linity
  163. ;    mov    ax,word ptr linity    ;  ...
  164. ;    mov    word ptr y+2,dx     ;  ...
  165. ;    mov    word ptr y,ax        ;  ...
  166.  
  167.     dec    k            ; we know the first iteration passed
  168.     mov    dx,word ptr linitx+2    ; add x += linitx
  169.     mov    ax,word ptr linitx    ;  ...
  170.     add    word ptr x,ax        ;  ...
  171.     adc    word ptr x+2,dx     ;  ...
  172.     mov    dx,word ptr linity+2    ; add y += linity
  173.     mov    ax,word ptr linity    ;  ...
  174.     add    word ptr y,ax        ;  ...
  175.     adc    word ptr y+2,dx     ;  ...
  176.     jmp    short doeither        ; branch around the julia switch
  177.  
  178. dojulia:                ; Julia Set initialization
  179.                     ; "fudge" Mandelbrot start-up values
  180.     mov    ax,word ptr x        ; switch x with linitx
  181.     mov    dx,word ptr x+2     ;  ...
  182.     mov    bx,word ptr linitx    ;  ...
  183.     mov    cx,word ptr linitx+2    ;  ...
  184.     mov    word ptr x,bx        ;  ...
  185.     mov    word ptr x+2,cx     ;  ...
  186.     mov    word ptr linitx,ax    ;  ...
  187.     mov    word ptr linitx+2,dx    ;  ...
  188.  
  189.     mov    ax,word ptr y        ; switch y with linity
  190.     mov    dx,word ptr y+2     ;  ...
  191.     mov    bx,word ptr linity    ;  ...
  192.     mov    cx,word ptr linity+2    ;  ...
  193.     mov    word ptr y,bx        ;  ...
  194.     mov    word ptr y+2,cx     ;  ...
  195.     mov    word ptr linity,ax    ;  ...
  196.     mov    word ptr linity+2,dx    ;  ...
  197.  
  198. doeither:                ; common Mandelbrot, Julia set code
  199.     mov    period,0        ; claim periodicity of 1
  200.     mov    savedand,1        ; initial periodicity check
  201.     mov    savedincr,1        ;  flag for incrementing periodicity
  202.     mov    word ptr savedx+2,0ffffh; impossible value of "old" x
  203.     mov    word ptr savedy+2,0ffffh; impossible value of "old" y
  204.     mov    orbit_ptr,0        ; clear orbits
  205.  
  206.     dec    kbdcount        ; decrement the keyboard counter
  207.     jns    short nokey        ;  skip keyboard test if still positive
  208.     mov    kbdcount,10        ; stuff in a low kbd count
  209.     cmp    show_orbit,0        ; are we showing orbits?
  210.     jne    quickkbd        ;  yup.  leave it that way.
  211.     mov    kbdcount,5000        ; else, stuff an appropriate count val
  212.     cmp    cpu,386         ; ("appropriate" to the CPU)
  213.     je    short quickkbd        ;  ...
  214.     cmp    word ptr delmin+2,1    ; is 16-bit math good enough?
  215.     ja    quickkbd        ;  yes. test less often
  216.     mov    kbdcount,500        ;  no.    test more often
  217. quickkbd:
  218.     call    far ptr keypressed    ; has a key been pressed?
  219.     cmp    ax,0            ;  ...
  220.     je    nokey            ; nope.  proceed
  221.     cmp    ax,'o'                  ; orbit toggle hit?
  222.     je    orbitkey        ;  yup.  show orbits
  223.     cmp    ax,'O'                  ; orbit toggle hit?
  224.     jne    keyhit            ;  nope.  normal key.
  225. orbitkey:
  226.     call    far ptr getakey     ; read the key for real
  227.     mov    ax,1            ; reset orbittoggle = 1 - orbittoggle
  228.     sub    ax,show_orbit        ;  ...
  229.     mov    show_orbit,ax        ;  ...
  230.     mov    kbdcount,10        ; adjust the keyboard
  231.     jmp    short nokey        ; pretend no key was hit
  232. keyhit: mov    ax,-1            ; return with -1
  233.     mov    color,ax        ; set color to -1
  234.     ret                ; bail out!
  235.  
  236. noke